Skip to content

WAIT: Derive organization status from affiliations; gate active on start date#1823

Open
maebeale wants to merge 3 commits into
mainfrom
maebeale/org-status-from-affiliations
Open

WAIT: Derive organization status from affiliations; gate active on start date#1823
maebeale wants to merge 3 commits into
mainfrom
maebeale/org-status-from-affiliations

Conversation

@maebeale

Copy link
Copy Markdown
Collaborator

REVIEW NEEDED: 🔬 Inspect — substantive logic: changes the semantics of the active scope (used in ~20 places) and the org-status callback

Stacked on #1809 (depends on its active_or_pending scope). Base it on maebeale/dual-org-affiliations; review after #1809.

What is the goal of this PR and why is this important?

How did you approach the change?

  • Two activeness scopes. Affiliation.active now also requires start_date to have arrived; active_or_pending (from Create job + Facilitator affiliations on registration and org linking #1809) keeps future-dated ("pending") affiliations. Added active? / active_or_pending? for in-memory filtering of preloaded records.
  • Reclassified every affiliation activeness check by intent:
    • Forward-looking → active_or_pending: org program-status (New/Ongoing/Reinstate), Organization.active/published?, the event dashboard's org list + program breakdown, the registration org snapshot, org/person end-date and "affiliations ended" displays, the org-index "active people" counts, and non-admin affiliation visibility.
    • Present-tense → active (stricter): a person's current-affiliations summary, "active facilitator" org names, and profile searchability (with_active_affiliations/published?), plus the person-show affiliations list.
  • Symmetric org-status callback. sync_organization_status_from_affiliations (renamed from the deactivate-only callback) now activates an Inactive org that gains an active-or-pending affiliation and deactivates one that loses them — toggling only Active↔Inactive, leaving manual states (Pending/Reinstate/Suspended/Unknown) untouched. Tracked via Ahoy.
  • Docs. AGENTS.md now states the bedrock "facilitators determine org status" rule and documents the two scopes.

Decisions to confirm

  • "Active people" counts (org index) use active_or_pending, so the count agrees with why the org is listed active. Alternative: strict active (people active today).
  • Non-admin affiliation visibility (AffiliationPolicy) uses active_or_pending, so a user can see their own upcoming facilitator role. Alternative: strict active.

Anything else to add?

  • New specs: active vs active_or_pending scopes + predicates for future-dated affiliations; symmetric status callback (reactivate, deactivate, pending-activates, manual-status-untouched); program-status treating a pending facilitator as Ongoing not Reinstate.
  • Broad regression run green across affiliation/organization/person models, decorators, policies, event dashboard, and the organizations/people/bookmarks/workshop-logs request specs.

🤖 Generated with Claude Code

Comment thread app/models/affiliation.rb
# unset). A future-dated affiliation (e.g. a Facilitator dated to an upcoming
# training's month) is therefore "pending" — counted by active_or_pending but
# not yet active.
scope :active, -> {

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🤖 From Claude: The crux: active now excludes future-dated affiliations (start_date not yet arrived). Sites that should still count an incoming facilitator were moved to active_or_pending; only present-tense checks (person summary, searchability, "active facilitator") keep this stricter scope.

Comment thread app/models/affiliation.rb
# activates an Inactive org that gains people and deactivates one that loses
# them. Only ever toggles between Active and Inactive — manual states (Pending,
# Reinstate, Suspended, Unknown) are left untouched so they stick.
def sync_organization_status_from_affiliations

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🤖 From Claude: Now symmetric (was deactivate-only). Guarded to toggle only Active↔Inactive — a manually set Pending/Reinstate/Suspended/Unknown is left alone, so admins keep control of those. Uses active_or_pending so an incoming facilitator activates the org.

Comment thread app/policies/affiliation_policy.rb Outdated
next relation if admin?
if authenticated?
relation.active
relation.active_or_pending

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🤖 From Claude: Decision to confirm: non-admins now see their own pending (future-dated) facilitator role via active_or_pending. Switch to active if upcoming roles should stay hidden until they start.

Base automatically changed from maebeale/dual-org-affiliations to main June 22, 2026 02:19
@maebeale maebeale force-pushed the maebeale/org-status-from-affiliations branch 2 times, most recently from 0e84108 to 61d6da8 Compare June 22, 2026 03:48
@maebeale maebeale marked this pull request as ready for review June 22, 2026 05:39
maebeale and others added 3 commits June 22, 2026 01:40
Builds on the affiliation-creation PR. Makes "is this org/person active" a
function of affiliations rather than a manually maintained field, and
distinguishes affiliations that have started from those still pending.

- Affiliation.active now also requires start_date to have arrived; the broader
  active_or_pending (introduced in the prior PR) keeps future-dated affiliations.
  Mirrored by active? / active_or_pending? for in-memory filtering.
- Reclassified every affiliation activeness check: forward-looking ones (org
  program-status, org active/published, the event dashboard's org list, the
  registration org snapshot, end-date/"ended" displays, people counts, non-admin
  affiliation visibility) use active_or_pending so an incoming facilitator counts;
  present-tense ones (person summary, "active facilitator" names, profile
  searchability) stay on the stricter active.
- Organization status callback is now symmetric: activates an Inactive org that
  gains an active-or-pending affiliation and deactivates one that loses them,
  toggling only Active<->Inactive and leaving manual states alone.
- Documented the bedrock "facilitators determine org status" rule and the two
  scopes in AGENTS.md.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Pending (future-dated) affiliations should be admin-only. The people index
and org-profile affiliation lists now show active-or-pending only to
super_users and the stricter active set to everyone else, replacing the
hand-rolled inline filters with the active?/active_or_pending? predicates.
Align AffiliationPolicy's (currently unused) authenticated scope to the same
rule so it can't leak pending if it's ever wired up.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
These four pages (people index, person profile, org index, org profile) are
becoming non-admin-visible. Centralize the "pending affiliations are admin-only"
rule in ApplicationController#include_pending_affiliations? and apply it to the
remaining activeness decisions that were unconditionally active_or_pending and
non-admin-visible: the org-index "active people" counts and the org-profile
affiliations-ended date check. Refactor the two already-gated view filters onto
the same helper so there's a single source of truth.

Left as-is: the admin-only program-status column, the admin-only edit-form date
decorators, and the person-show affiliations list (already strict active).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@maebeale maebeale force-pushed the maebeale/org-status-from-affiliations branch from 61d6da8 to 3b5f259 Compare June 22, 2026 05:41
@maebeale maebeale changed the title Derive organization status from affiliations; gate active on start date WAIT: Derive organization status from affiliations; gate active on start date Jun 22, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant